#include "usb_app.h"

#include "drv_usb_hw.h"
#include "drv_usb_core.h"
#include "usbh_usr.h"
#include "usbh_printer_core.h"
#include "usbh_pipe.h"
#include "usbd_printer_core.h"


static uint8_t test_print_codes[] = 
{
0x1b,0x40,0x1b,0x70,0x00,0x32,0xff,0x1c,0x21,0x08,0x1b,0x21,0x10,0xd5,0xfd,0xd4,
0xda,0xd6,0xb4,0xd0,0xd0,0xb2,0xe2,0xca,0xd4,0xb4,0xf2,0xd3,0xa1,0x0a,0x1c,0x21,
0x00,0x1b,0x21,0x00,0xd5,0xe2,0xca,0xc7,0xc4,0xfa,0xd5,0xfd,0xd4,0xda,0xd1,0xa1,
0xd4,0xf1,0xb5,0xc4,0xb2,0xe2,0xca,0xd4,0xb4,0xf2,0xd3,0xa1,0xc4,0xda,0xc8,0xdd,
0xa1,0xa3,0x0a,0x0a,0x0a,0x1d,0x56,0x01,0x1c,0x21,0x08,0x1b,0x21,0x10,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0xd3,0xc5,0xbb,0xdd,0xc8,0xaf,0x0a,0x0a,0x1c,0x21,0x00,0x1b,0x21,
0x00,0xb2,0xe2,0xca,0xd4,0xd3,0xc5,0xbb,0xdd,0xc8,0xaf,0x0a,0x0a,0x0a,0x0a,0x0a,
0x1d,0x56,0x01,0x1b,0x42,0x02,0x01,
};

usbh_host usb_host;
usb_core_driver usbh_core;

/*!
    \brief      main routine
    \param[in]  none
    \param[out] none
    \retval     int
*/

static usb_urb_state usbh_urb_wait_2 (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time)
{
    uint32_t timeout = 0U;
    usb_urb_state urb_status = URB_IDLE;
    timeout = uhost->control.timer;

    while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) {
        if (URB_NOTREADY == urb_status) {
            break;
        } else if (URB_STALL == urb_status) {
            uhost->control.ctl_state = CTL_SETUP;
            break;
        } else if (URB_ERROR == urb_status) {
            uhost->control.ctl_state = CTL_ERROR;
            break;
        } else if ((wait_time > 0U) && ((uhost->control.timer - timeout) > wait_time)) {
            /* timeout for in transfer */
            uhost->control.ctl_state = CTL_ERROR;
            break;
        } else {
            /* no operation, just wait */
        }
    }

    return urb_status;
}

extern void ctc_config(void);

usb_core_driver usbd_printer;

void usb_app_host_init(void) {
	
	int sendLen = 0;
	int sendDataLen = 64;
	printf("> main \r\n");
	//usb_gpio_config();
	usb_host_gpio_config();
	//usb_rcu_config();
	usb_host_rcu_config();
	usb_timer_init();

    /* configure GPIO pin used for switching VBUS power and charge pump I/O */
    //usb_vbus_config();

    /* register device class */
    usbh_class_register(&usb_host, &usbh_printer);

    usbh_init(&usb_host,
              &usbh_core,
              USB_CORE_ENUM_HS,
              &usr_cb);

    /* enable interrupts */
    //usb_intr_config();
		usb_host_intr_config();
		#ifdef USE_IRC48M
    /* CTC peripheral clock enable */
    rcu_periph_clock_enable(RCU_CTC);

    /* CTC configure */
    ctc_config();

    while (ctc_flag_get(CTC_FLAG_CKOK) == RESET) {
    }
		
		#endif
		printf("end ---\r\n");
		int pre_state = -1;
    while (1) {
        /* Host state handler */
			pre_state = usb_host.cur_state;
			usbh_core_task(&usb_host);
			if (usb_host.cur_state != pre_state) {
				printf("before:state:%d\r\n",pre_state);
				printf("after:state:%d\r\n",usb_host.cur_state);
				printf("\r\n");
				if (usb_host.cur_state == HOST_CLASS_ENUM) {
					usb_mdelay (3000U);
					usb_host.control.ctl_state = CTL_DATA_OUT;
			
					usbh_printer_handler *printer = (usbh_printer_handler *)usb_host.active_class->class_data;
					printf("print data ep:%d\r\n",usb_host.control.pipe_out_num);
					printf("print data ep 2:%d\r\n",printer->pipe_out);
					printf("\r\n");
					
					while(sendLen < 135) {
						usbh_pipe_toggle_set(usb_host.data, usb_host.control.pipe_out_num, 1U);
						if (135 - sendLen >= 64) {
							sendDataLen = 64;
						} else {
							sendDataLen = 135 -sendLen;
						}
						usbh_data_send(&usbh_core,&test_print_codes[sendLen],printer->pipe_out,sendDataLen);
						
						if (URB_DONE == usbh_urb_wait_2 (&usb_host, usb_host.control.pipe_out_num, DATA_STAGE_TIMEOUT)) {
							usb_host.control.ctl_state = CTL_STATUS_IN;
							sendLen += sendDataLen;
							printf("send data len:%d\r\n",sendLen);
						}
					}
				  
					//usb_mdelay (10000U);
					
					printf("print data done\r\n");
					printf("\r\n");
				}
			}
    }
}

void usb_app_device_init(void) {
	
	//usb_gpio_config();
	usb_device_gpio_config();
  usb_device_rcu_config();
  usb_timer_init();
	printf("usb device inter1\r\n");
  usbd_init (&usbd_printer,
              USB_CORE_ENUM_FS,
              &printer_desc,
              &usbd_printer_cb);
	printf("usb device inter2\r\n");
	usbd_connect(&usbd_printer);
	printf("usb device inter3\r\n");
	usb_device_intr_config();
	
	printf("usb device inter\r\n");
	/*
	rcu_periph_clock_enable(RCU_CTC);
  ctc_config();

  while (ctc_flag_get(CTC_FLAG_CKOK) == RESET) {
  }
	*/
	printf("usb device finish\r\n");

}
